﻿using System;
using System.Activities;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Windows.Data;
using System.Windows.Threading;
using Common;
using Common.Activities;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.ViewModel;
using Module2.Services;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace Module2.ViewModels
{
    public class WorkflowViewerViewModel : INotifyPropertyChanged
    {
        private WorkflowApplication _currentWorkflowApplication;
        private System.Activities.Activity _currentActivity;
        private string _activeActivityBookmark;
        private readonly List<ActivityDescriptor> _model;
        private ObservableCollection<UserStepActivity> _userSteps;

        public ICollectionView ActivityCV { get; private set; }
        public ICollectionView BookmarkCV { get; private set; }
        public DelegateCommand CompleteCommand { get; private set; }

        public WorkflowViewerViewModel()
        {
            _model = Helper.ActivityList;
            ActivityCV = new ListCollectionView(_model);
            ActivityCV.CurrentChanged += new EventHandler(SelectedItemChanged);

            _userSteps = new ObservableCollection<UserStepActivity>();
            BookmarkCV = new ListCollectionView(this._userSteps);
            BookmarkCV.CurrentChanged += new EventHandler(SelectedBookmarkChanged);

            CompleteCommand = new DelegateCommand(OnComplete);
        }

        #region Event Handlers
        private void SelectedItemChanged(object sender, EventArgs e)
        {
            // Publish the DataItemSelected event when the current selection changes.
            ActivityDescriptor item = ActivityCV.CurrentItem as ActivityDescriptor;
            if (item != null && item.Xaml != null)
            {
                Helper.TryLoadAndValidateActivity(item.Xaml, out _currentActivity);

                _userSteps.Clear();

                UserStepSequence rootActivitySequence = default(UserStepSequence);
                Helper.InspectActivity(_currentActivity, _userSteps, ref rootActivitySequence);
                rootActivitySequence.UserStepSequenceChanged += UserStepSequenceChanged;
                _activeActivityBookmark = rootActivitySequence.BookmarkName.Expression.ToString();

                _currentWorkflowApplication = new WorkflowApplication(_currentActivity);
                _currentWorkflowApplication.Run();
            }
        }

        private void SelectedBookmarkChanged(object sender, EventArgs e)
        {
            ActivityDescriptor item = ActivityCV.CurrentItem as ActivityDescriptor;

            if (item != null && item.Xaml != null)
            {
                //"No Activity Selected"
                UserStepActivity userStep = BookmarkCV.CurrentItem as UserStepActivity;                
                if (userStep != null)
                {
                    _currentWorkflowApplication.ResumeBookmark(_activeActivityBookmark, userStep.BookmarkNameValue);            
                }
            }
        }

        private void UserStepSequenceChanged(object sender, UserStepSequenceChangedEventArgs e)
        {
            Debug.Write(e.Message);
            RaisePropertyChanged("BookmarkCV");
        }

        private void OnComplete()
        {
            // TODO: handle user completion of client activity sequence
            var item = ActivityCV.CurrentItem as ActivityDescriptor;
        }
        #endregion

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raises this object's PropertyChanged event.
        /// </summary>
        /// <param name="propertyName">The property that has a new value.</param>
        void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged == null) return;
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

    }
}
